<template>
    <div class="menu-tree-editor">
      <el-row :gutter="20">
        <!-- 左侧树结构 -->
        <el-col :span="10">
          <el-card>
            <div slot="header">
              <span>菜单结构</span>
              <el-button type="primary" size="mini" @click="addRoot" style="margin-left: 20px;">新增一级菜单</el-button>
            </div>
            <el-tree
              :data="menu"
              :props="defaultProps"
              node-key="id"
              highlight-current
              draggable
              :allow-drop="allowDrop"
              @node-drop="handleNodeDrop"
              @node-click="handleNodeClick"
              ref="menuTree"
              :expand-on-click-node="false"
            >
              <span slot-scope="{ node, data }" class="custom-tree-node">
                <span>
                  <i :class="data['el-iconClass']" style="margin-right: 6px;"></i>
                  {{ data.name }}
                </span>
                <span>
                  <el-button size="mini" type="text" @click.stop="addChild(data)">添加</el-button>
                  <el-button size="mini" type="text" @click.stop="remove(data)">删除</el-button>
                </span>
              </span>
            </el-tree>
          </el-card>
        </el-col>
  
        <!-- 右侧编辑面板 -->
        <el-col :span="14">
          <el-card>
            <div slot="header"><span>编辑菜单项</span></div>
  
            <el-form v-if="selected" :model="selected" label-width="100px">
              <el-form-item label="名称">
                <el-input v-model="selected.name" />
              </el-form-item>
              <el-form-item label="图标类名">
                <el-row type="flex" justify="space-between" align="middle" :gutter="20">
                  <el-col :span="20">
                    <el-input v-model="selected['el-iconClass']" placeholder="输入图标类名" readonly />
                  </el-col>
                  <el-col :span="2">
                    <i :class="selected['el-iconClass']" class="el-icon" style="font-size: 24px;"></i>
                  </el-col>
                  <el-col :span="4">
                    <icon-picker v-model="selected['el-iconClass']" @selectIcon="selectIcon">
                      <template v-slot:trigger>
                        <el-button type="primary">选择图标</el-button>
                      </template>
                    </icon-picker>
                  </el-col>
                </el-row>
              </el-form-item>
              <el-form-item label="表名">
                <el-input v-model="selected.tableName" />
              </el-form-item>
              <el-form-item label="是否显示">
                <el-switch v-model="selected.show" />
              </el-form-item>
              <el-form-item label="是否启用">
                <el-switch v-model="selected.able" />
              </el-form-item>
            </el-form>
  
            <el-alert
              v-else
              title="请选择一个菜单节点进行编辑"
              type="info"
              show-icon
              center
            />
          </el-card>
  
          <!-- JSON 输出 -->
          <el-card style="margin-top: 20px;">
            <div slot="header">
              <span>导出配置</span>
              <el-button type="success" size="mini" @click="generateJson" style="float: right;">生成配置</el-button>
            </div>
            <el-input type="textarea" v-model="jsonOutput" :rows="15" readonly />
          </el-card>
        </el-col>
      </el-row>
    </div>
  </template>
  
  <script>
  import IconPicker from '@/components/Config/IconPicker.vue'
  
  export default {
    name: "MenuTreeEditor",
    components: {
      IconPicker
    },
    data() {
      return {
        menu: [],
        selected: null,
        jsonOutput: '',
        idCounter: 1,
        defaultProps: {
          children: 'children',
          label: 'name'
        }
      }
    },
    methods: {
      generateId() {
        return this.idCounter++
      },
      selectIcon(icon){
        this.selected["el-iconClass"] = icon
      },
      addRoot() {
        const node = this.createNode('新菜单')
        this.menu.push(node)
      },
      addChild(parent) {
        if (!parent.children) {
          this.$set(parent, 'children', [])
        }
        const child = this.createNode('子菜单')
        parent.children.push(child)
        this.$nextTick(() => {
          this.$refs.menuTree.setCurrentKey(child.id)
          this.selected = child
          this.$refs.menuTree.setExpanded(parent, true);
        })
      },
      remove(node) {
        const removeNode = (list, id) => {
          const index = list.findIndex(item => item.id === id)
          if (index !== -1) {
            list.splice(index, 1)
            return true
          }
          for (const item of list) {
            if (item.children && removeNode(item.children, id)) {
              return true
            }
          }
          return false
        }
        removeNode(this.menu, node.id)
        if (this.selected && this.selected.id === node.id) {
          this.selected = null
        }
      },
      handleNodeClick(node) {
        this.selected = node
      },
      createNode(name) {
        return {
          id: this.generateId(),
          name,
          "el-iconClass": "",
          tableName: "",
          show: true,
          able: true,
          children: []
        }
      },
      generateJson() {
        const cleanData = list => {
          return list.map(item => {
            const obj = {
              name: item.name,
              "el-iconClass": item["el-iconClass"],
              tableName: item.tableName,
              show: item.show,
              able: item.able
            }
            if (item.children && item.children.length) {
              obj.children = cleanData(item.children)
            }
            return obj
          })
        }
        this.jsonOutput = JSON.stringify({ menu: cleanData(this.menu) }, null, 2)
      },
      // 拖拽相关
      allowDrop(draggingNode, dropNode, type) {
        return type !== 'inner' || dropNode.level < 3
      },
      handleNodeDrop(draggingNode, dropNode, dropType) {
        const findAndRemove = (list, id) => {
          for (let i = 0; i < list.length; i++) {
            if (list[i].id === id) {
              return list.splice(i, 1)[0]
            } else if (list[i].children) {
              const found = findAndRemove(list[i].children, id)
              if (found) return found
            }
          }
        }
  
        const insertNode = (list, node, targetId, dropType) => {
          for (let i = 0; i < list.length; i++) {
            if (list[i].id === targetId) {
              if (dropType === 'before') list.splice(i, 0, node)
              else if (dropType === 'after') list.splice(i + 1, 0, node)
              else if (dropType === 'inner') {
                if (!list[i].children) list[i].children = []
                list[i].children.push(node)
              }
              return true
            } else if (list[i].children) {
              if (insertNode(list[i].children, node, targetId, dropType)) return true
            }
          }
        }
  
        const draggedData = findAndRemove(this.menu, draggingNode.data.id)
        insertNode(this.menu, draggedData, dropNode.data.id, dropType)
      }
    }
  }
  </script>
  
  <style scoped>
  .menu-tree-editor {
    padding: 20px;
  }
  .custom-tree-node {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
  </style>
  